package x.ovo.wechat.bot.impl.core;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Cookie;
import okhttp3.HttpUrl;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.crypto.SecureUtil;
import org.dromara.hutool.json.JSONObject;
import org.dromara.hutool.json.JSONUtil;
import x.ovo.wechat.bot.core.Constant;
import x.ovo.wechat.bot.core.exception.LoginException;
import x.ovo.wechat.bot.core.http.session.Session;
import x.ovo.wechat.bot.impl.config.ClientConfig;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Data
@Slf4j(topic = "HotReload")
public class HotReload implements Serializable {

    private Session session;
    private Map<String, List<Cookie>> cookies = new HashMap<>();
    private static final ClientConfig config = ClientConfig.get();
    private static final byte[] ENCODE_KEY = SecureUtil.md5(ClientConfig.get().getEncryptKey()).getBytes();


    public static HotReload create(Session session, Map<String, List<Cookie>> cookies) {
        HotReload hotReload = new HotReload();
        hotReload.session = session;
        hotReload.cookies = cookies;
        return hotReload;
    }

    public void save() {
        byte[] bytes = config.getEncryptLoginInfo() ? encode(this.toJsonString()) : this.toJsonString().getBytes();
        FileUtil.writeBytes(bytes, Constant.Files.LOGIN_FILE);
        log.info("自动登录信息已保存");
    }

    public static HotReload load() {
        if (FileUtil.exists(Constant.Files.LOGIN_FILE)) {
            byte[] bytes = FileUtil.readBytes(Constant.Files.LOGIN_FILE);
            String decode = config.getEncryptLoginInfo() ? decode(bytes) : new String(bytes);
            HotReload obj = toObj(decode);
            if (Objects.isNull(obj.getSession()) || StrUtil.isBlank(obj.getSession().getWxUin()) || CollUtil.isEmpty(obj.getCookies()))
                throw new LoginException("自动登录信息已损坏");
            return obj;
        }
        throw new LoginException("自动登录信息不存在");
    }

    public static void delete() {
        FileUtil.del(Constant.Files.LOGIN_FILE);
    }

    private static byte[] encode(String string) {
        return SecureUtil.aes(ENCODE_KEY).encrypt(string);
    }

    private static String decode(byte[] bytes) {
        return SecureUtil.aes(ENCODE_KEY).decryptStr(bytes);
    }

    private static HotReload toObj(String json) {
        JSONObject object = JSONUtil.parseObj(json);
        HotReload hotReload = new HotReload();
        hotReload.session = object.getBean("session", Session.class);
        List<JSONObject> cookies = object.getJSONArray("cookies").stream()
                .map(JSONUtil::parseObj)
                .toList();
        cookies.forEach(cookieJson -> cookieJson.keySet().forEach(host -> {
            HttpUrl url = new HttpUrl.Builder().scheme("https").host(host).build();
            List<Cookie> list = cookieJson.getJSONArray(host).stream().map(String::valueOf).map(s -> Cookie.parse(url, s)).toList();
            hotReload.getCookies().put(host, list);
        }));
        return hotReload;
    }


    private String toJsonString() {
        JSONObject object = JSONUtil.ofObj().set("session", this.session);

        List<JSONObject> cookies = this.cookies.entrySet().stream()
                .map(entry -> {
                    List<String> list = entry.getValue().stream()
                            .map(Cookie::toString)
                            .toList();
                    return JSONUtil.ofObj().set(entry.getKey(), list);
                }).toList();
        object.set("cookies", cookies);
        return JSONUtil.toJsonPrettyStr(object);
    }
}
